from PySide2.QtWidgets import QApplication, QMessageBox, QTableWidgetItem, QComboBox
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QPixmap
from PySide2.QtCore import Qt
from MySQl import MySQlUtil
from DataOpt import Data
from ProductionSystemCore import ProductionSystem
import ast
from Sid import RuidGet

# 主窗口类
class MainWindow:
    """主窗体及其弹出框类"""
    def __init__(self, KB, features, animal):
        self.main_ui = QUiLoader().load("main.ui")  # 主界面
        self.main_ui.setWindowIcon(QPixmap("icon1.jpeg"))  # 设置图标
        self.dialog_ui = QUiLoader().load("dialog.ui")  # 修改界面
        self.KB = [] #知识库，例：[[条件1,条件2,...,结论],...]
        for rule in KB:
            self.KB.append(rule[1:])

        #生成id的对象
        self.sid = RuidGet()

        #存储被更改行的信息
        self.changed_row = {}
        #print(self.KB)
        #print("KB",KB)
        self.KB_1 = KB #知识库,包含id，例：[[id1,条件1,条件2,...,结论],[id2,条件1...结论]...]
        self.features = features  # 特征，例[特征1，特征2...]
        # 得到处理数据库的对象
        self.mySQlUtil = MySQlUtil()
        # 初始选中的特征
        self.checkedFeature = []
        # 初始化综合数据库
        self.DB = []
        self.target = "" #反向推理的目标

        self.flag = False  # 标识符，用于已选事实框

        self.animal = animal

        #是否捕获更改标志
        self.flag_1 = False

        # 初始化产生式系统
        #print(rule)
        self.ps = ProductionSystem(self.DB, self.KB, animal)

        #存储最终结果
        self.conclusion = ""
        # 给特征下拉框添加数据
        # self.main_ui.comboBox.addItem("请选择事实...")
        self.main_ui.comboBox.addItems(features)
        self.main_ui.comboBox.activated.connect(self.addFeature)
        #显示新增界面
        self.main_ui.openDialog1.clicked.connect(self.showDialog1)
        #提交新增的规则
        self.dialog_ui.CommitButton.clicked.connect(self.getRules)
        #选择推理目标
        self.main_ui.comboBox_2.activated.connect(self.getTarget)
        #给结论下拉框添加数据
        # self.main_ui.comboBox_2.addItem("选择逆推目标...")
        self.main_ui.comboBox_2.addItems(animal)
        # 正向推理
        self.main_ui.ForwardButton.clicked.connect(self.forward)
        # 反向推理
        self.main_ui.BackwardButton.clicked.connect(self.backward)
        #清空所有Brower框
        self.main_ui.clear.clicked.connect(self.clearBrowers)
        #修改系统名
        self.main_ui.commit_1.clicked.connect(self.renameSystem)
        #删除选中行-只能单行删除
        self.main_ui.deleteButton.clicked.connect(self.deleteRule)
        #检测单元格变化
        self.main_ui.ruleTable.cellChanged.connect(self.changeRow)
        #确认更改规则
        self.main_ui.commit_2.clicked.connect(self.changeRule)
        #提交新增的动物名
        self.main_ui.commit_3.clicked.connect(self.addAnimal)

    # 显示修改框
    def showDialog1(self):
        self.dialog_ui.setWindowIcon(QPixmap("icon1.jpeg"))
        print("show")
        self.dialog_ui.show()

    # 新增最终结论
    def addAnimal(self):
        animal = self.main_ui.NewName_2.toPlainText()
        if self.mySQlUtil.insertAnimal(animal):
            QMessageBox.information(
                self.main_ui,
                '操作成功',
                'good')
            self.animal.append(animal)
            self.main_ui.comboBox_2.clear()
            self.main_ui.comboBox_2.addItems(self.animal)
        else:
            QMessageBox.critical(
                self.main_ui,
                '错误',
                '插入出错,可能有重复的动物！')


    #确认更改，提交数据库
    def changeRule(self):
        choice = QMessageBox.question(
            self.main_ui,
            '提示',
            '确认更改？')
        if choice == QMessageBox.Yes:
            info = self.changed_row
            self.mySQlUtil.updateRule(info["id"],info["pres"],info["conclusion"])
            #更新知识库
            rule=[]
            rule.append(id)
            pres = ast.literal_eval(info["pres"])
            for pre in pres:
                rule.append(pre)
            rule.append(info["conclusion"])
            self.KB[info["row"]] = rule[1:]
            self.KB_1[info["row"]] = rule

    #获取更改行信息
    def changeRow(self,row,column):
        if self.flag_1:
            info = {}
            change_value = self.main_ui.ruleTable.item(row, column).text()
            rule = self.KB_1[row] #取出该条规则
            info["id"] = rule[0] #得到id
            info["row"] = row
            if column==1: #更改前提
                info["pres"] = change_value
                info["conclusion"] = rule[-1]
            elif column==2: #更改结论
                info["conclusion"] = change_value
                info["pres"] = rule[1:-1]
            else:
                pass
            self.changed_row = info

    #删除选中的规则
    def deleteRule(self):
        choice = QMessageBox.question(
            self.main_ui,
            '提示',
            '确认删除？')
        if choice == QMessageBox.Yes:
            index = self.main_ui.ruleTable.currentRow() #得到当前选中行
            rule = self.KB_1[index]
            self.KB_1.pop(index) #移除知识库的rule
            self.KB.pop(index) #移除知识库的rule
            id = rule[0]
            self.mySQlUtil.deleteRule(id)
            self.main_ui.ruleTable.removeRow(index)

    # 修改系统名
    def renameSystem(self):
        name = self.main_ui.NewName.toPlainText()
        self.main_ui.setWindowTitle(name)

    #清空所有Brower
    def clearBrowers(self):
        self.main_ui.processBrower.clear()
        self.main_ui.ksBrowser.clear()
        self.main_ui.FeatureBrower.clear()
        self.DB = []
        self.process = []
        self.flag = True

    #提交新增的知识
    def getRules(self):
        self.flag_1 = False #不必监听新增事件
        # 获取新增的条件
        re_feature = self.dialog_ui.FeatureInput.toPlainText()
        self.dialog_ui.FeatureInput.clear()
        features = []  # 规则前件
        mid_feature = []
        for feature in re_feature.split("," or "，"):
            features.append(feature)
            # 若已经有了此特征就不需要添加进数据库
            if feature not in self.features:
                self.features.append(feature)
                mid_feature.append(feature)
        # 获取新增的结论
        answer = self.dialog_ui.AnswerInput.toPlainText()
        self.dialog_ui.AnswerInput.clear()
        id = self.sid.get_int_ruid()
        self.mySQlUtil.insertRule(id,features, answer) #插入新增的知识
        if answer not in features:
            mid_feature.append(answer)
            self.features.append(answer)
        self.main_ui.comboBox.clear()
        self.main_ui.comboBox.addItems(self.features)
        self.mySQlUtil.insertFeature(mid_feature)  # 插入新增的特征
        rule = features[:]
        rule.append(answer) #得到新增的知识
        self.KB.append(rule[:])
        rule.insert(0,id) #得到新增知识,带id
        self.KB_1.append(rule)
        ruleTable = self.main_ui.ruleTable
        rowcount = ruleTable.rowCount()
        #刷新表格
        ruleTable.insertRow(rowcount)
        id_item = QTableWidgetItem(str(id))
        id_item.setFlags(Qt.ItemIsEnabled)
        conclusion_item = QTableWidgetItem(answer)
        conclusion_item.setFlags(Qt.ItemIsEnabled)
        ruleTable.setItem(rowcount, 0, id_item)  # 必须得字符型数据
        ruleTable.setItem(rowcount, 1, QTableWidgetItem(str(features)))
        ruleTable.setItem(rowcount, 2, conclusion_item)
        # print("KB_1",self.KB_1)
        # print("KB",self.KB)
        # print("self.features",self.features)
        self.flag_1 = True
        #self.main_ui.ruleBrower.append(f"{rule[:-1]} -> {rule[-1]}")

    # 显示规则
    def showAllData(self):
        #ruleBrower = self.main_ui.ruleBrower
        ruleTable = self.main_ui.ruleTable
        ruleTable.setColumnWidth(1, 450)
        i = 0
        for rule in self.KB_1:
            ruleTable.insertRow(i) #插入一行
            # print("rule[0]",rule[0])
            id_item = QTableWidgetItem(str(rule[0]))
            id_item.setFlags(Qt.ItemIsEnabled)
            conclusion_item = QTableWidgetItem(rule[-1])
            ruleTable.setItem(i, 0, id_item) #必须得字符型数据
            ruleTable.setItem(i, 1, QTableWidgetItem(str(rule[1:-1])))
            ruleTable.setItem(i, 2, conclusion_item)
            i+=1
        self.flag_1 = True

    #得到反向推理需要的目标
    def getTarget(self):
        self.main_ui.processBrower.clear()
        self.main_ui.ksBrowser.clear()
        # 点击推理后,再次选择结论就清除浏览框,重置综合数据库
        if self.flag:
            self.DB = []
            self.main_ui.FeatureBrower.clear()
        self.flag = False  # 复原
        self.ps.DB = self.DB
        index = self.main_ui.comboBox_2.currentIndex()
        print(self.animal[index])
        self.target = self.animal[index]

    # 新增选中的规则
    def addFeature(self):
        self.main_ui.processBrower.clear()
        self.main_ui.ksBrowser.clear()
        #点击推理后,再次选择规则就清除浏览框,重置综合数据库
        if self.flag:
            self.DB = []
            self.main_ui.FeatureBrower.clear()
        self.flag = False #复原
        index = self.main_ui.comboBox.currentIndex()
        print(index)
        self.DB.append(self.features[index])
        self.main_ui.FeatureBrower.append(f"{self.features[index]}\t")

    # 显示综合数据库
    def showDB(self):
        for fact in self.ps.DB:
            self.main_ui.ksBrowser.append(fact)

    # 显示推理过程
    def showProcess(self):
        for process in self.ps.process:
            self.main_ui.processBrower.append(process)
        self.ps.process = []
        self.main_ui.processBrower.append(f"最终：\n\t{self.conclusion}")

    # 正向推理
    def forward(self):
        #点击之前先清除文本框
        self.flag = True #已经推理了,下一轮把已选事实清空
        self.main_ui.processBrower.clear()
        self.main_ui.ksBrowser.clear()
        self.ps.DB = self.DB
        #print(self.ps.forwardReasoning())
        self.conclusion = self.ps.forwardReasoning()
        self.showDB()
        self.showProcess()

    #反向推理
    def backward(self):
        # 点击之前先清除文本框
        self.main_ui.processBrower.clear()
        self.main_ui.ksBrowser.clear()
        self.conclusion = self.ps.backwardReasoning(self.target)
        self.ps.DB = self.DB
        self.showProcess()
        self.showDB()
        if self.conclusion == "推理失败":
            choice = QMessageBox.question(
                self.main_ui,
                '追加',
                '是否继续追加事实？')
            if choice == QMessageBox.Yes:
                self.flag = False #继续追加，下一轮选事实不清空初始事实库
            else:
                self.flag = True #不推理了,下一轮选事实清空初始事实库
        else:
            self.flag = True #推理成功

if __name__ == "__main__":
    app = QApplication([])
    data = Data()
    data.dataBase()
    mainWindow = MainWindow(data.KB, data.Feature, data.Animal)
    mainWindow.main_ui.show()
    mainWindow.showAllData()
    mySQlUtil = MySQlUtil()
    app.exec_()
